package java8;

import java8.pojo.IPrint;
import java8.pojo.Messenger;
import java8.pojo.User;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public class MethodReferenceSample {

    static IPrint printer;

    static Messenger messenger = new Messenger();

    public static void main(String[] args) {
        // ================================================
        // 1. 静态方法引用
        // lambda: (args) -> ClassName.staticMethod(args)
        // 方法引用: ClassName::staticMethod
        // ================================================
        // 1.1 过去的写法
        printer = new IPrint() {
            @Override
            public void print(String text) {
                Messenger.accept(text);
            }
        };
        // 1.2 lambda 表达式写法
        printer = text -> Messenger.accept(text);
        // 1.3 方法引用写法
        printer = Messenger::accept;
        // 输出: accepted message: Hello
        printer.print("Hello");

        // ================================================
        // 2. 现有对象的实例方法引用
        // lambda: (args) -> object.instanceMethod(args)
        // 方法引用: object::instanceMethod
        // ================================================
        // 2.1 过去的写法
        printer = new IPrint() {
            @Override
            public void print(String text) {
                messenger.send(text);
            }
        };
        // 2.2 lambda 表达式写法
        printer = text -> messenger.send(text);
        // 2.3 方法引用写法
        printer = messenger::send;
        // 输出: sending message: Hello
        printer.print("Hello");

        // ================================================
        // 3. 特定类型的任意对象的实例方法引用 (要求操纵的所有对象都是同一个类型)
        // lambda: (arg0, arg1) -> arg0.instanceMethod(arg1)
        // 方法引用: ClassName::instanceMethod
        // ================================================
        // 对列表元素排序案例
        List<Integer> seqList = Arrays.asList(1, 3, 5, 2, 4, 6);
        // 输出: 135246
        seqList.forEach(System.out::print);
        System.out.println(); // 换行
        // 3.1 过去的写法
        Collections.sort(seqList, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        });
        // 3.2 lambda 表达式写法
        Collections.sort(seqList, ((o1, o2) -> o1.compareTo(o2)));
        // 或者使用 Java 8 提供的 List.sort 方法排序
        seqList.sort((o1, o2) -> o1.compareTo(o2));
        // 3.3 方法引用写法
        Collections.sort(seqList, Integer::compareTo);
        // 或者使用 Java 8 提供的 List.sort 方法排序
        seqList.sort(Integer::compareTo);
        // 输出: 123456
        seqList.forEach(System.out::print);
        System.out.println(); // 换行

        // 案例 2
        // List 转 Map
        List<User> users = Arrays.asList(
                new User("Annie", 20),
                new User("Cindy", 18),
                new User("Jason", 19)
        );
        Map<String, User> userMap;
        // 3.1 过去的写法
        userMap = new HashMap<>();
        for (User user : users) {
            userMap.put(user.getName(), user);
        }
        // 3.2 lambda 表达式写法
        userMap = users.stream().collect(
                Collectors.toMap(u -> u.getName(), u -> u, (u1, u2) -> u1)); // key 冲突时保留第一个
        // 3.3 方法引用写法
        userMap = users.stream().collect(
                Collectors.toMap(User::getName, Function.identity(), (u1, u2) -> u1)); // key 冲突时保留第一个
        // 输出: {Annie=User(name=Annie, age=20), Jason=User(name=Jason, age=19), Cindy=User(name=Cindy, age=18)}
        System.out.println(userMap);


        // ================================================
        // 4. 构造函数引用
        // lambda: (args) -> new ClassName(args)
        // 方法引用: ClassName::new
        // ================================================
        // 4.1 过去的写法
        printer = new IPrint() {
            @Override
            public void print(String text) {
                new Messenger(text);
            }
        };
        // 4.2 lambda 表达式写法
        printer = text -> new Messenger(text);
        // 4.3 方法引用写法
        printer = Messenger::new;
        // 输出: sending message: Welcome
        printer.print("Welcome");

        // 案例 2
        Supplier<Messenger> messengerSupplier = Messenger::new;
        // 输出: sending message: Hi
        messengerSupplier.get().send("Hi");
    }

}